Optional Variance Annotations for Type Parameters
v4.7からin/outを用いてvarianceを明示できる
例
Getter型をcovariantとする場合は、型引数にoutを書く
code:ts
type Getter<out T> = () => T;
このTを引数で使おうとするとerrorになる
code:ts
type Getter<out T> = (a: T) => T; // error
Setter型をcontravariantにする場合は、型引数にinを書く
code:ts
type Setter<in T> = (value: T) => void;
State型をinvariantにする場合は、in out Tと書く
code:ts
type State<in out T> = {
get: () => T;
set: (value: T) => void;
}
こうするとStateはinvariantになる
雑に言えば、State<Cat>とState<Animal>のような型の間に部分型関係がなくなる
ちなみに逆順でout inとは書けないmrsekut.icon
構造的部分型にvarianceは重要ではないが、導入された理由 ref 読み手が理解するのに役立つ
その型のvarianceが即座にわかる
その型の型変数が使われる場所の意図が読める
推論のパフォーマンス向上につながる
TypeScriptは最適化としてvarianceを推論するが、その速度が上がる
推論に失敗することもあるので、その補助になる
書ける状況はかなり制限されているっぽい
関数の定義時には書けないのかmrsekut.icon
code:ts
function add<in T>(arr: Array<T>) {
}
これ、関数型にしか使えないのか?
以下のようには書けない?
code:ts
type InvariantArray<in out T> = Array<T> // error
Variance annotations are only supported in type aliases for object, function, constructor, and mapped types
書けないらしい
というかtypeで定義した時は制限があるという感じかmrsekut.icon
interfaceを使えば書ける
code:ts
interface InvariantArray<in out T> extends Array<T> {}